﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
using ACompany.OrderProcessing.Infrastructure;

namespace ACompany.OrderProcessing.Model
{
    public abstract class BusinessBase<T> : IEntity where T : IEntity
    {
        private Guid _id = Guid.Empty;
        public Guid Id
        {
            get { return _id; }
            set { _id = value; }
        }

        public bool IsTransient()
        {
            return this.Id == Guid.Empty;
        }

        public override bool Equals(object obj)
        {
            if (obj != null && obj.GetType() == typeof(T))
            {
                if (this.HasSameIdentifierAs((T)obj))
                {
                    //' Both entities are persistant so we are able to compare the identifiers
                    return true;
                }
                else if (this.HasDifferentPersistenceContextAs((T)obj))
                {
                    // One entity is transient one is persistant so that cannot be eqaul
                    return false;
                }
                else //' Neither Entity has an Identity
                {
                    return false;
                }
            }

            return false;
        }

        private bool HasDifferentPersistenceContextAs(T entityToCompare)
        {
            return !(IsTransient() && entityToCompare.IsTransient());
        }
        public override int GetHashCode()
        {
            if (IsTransient())
            {
                return this.GetType().FullName.GetHashCode();
            }
            else
            {
                return string.Format("{0}{1}", this.GetType().FullName, this.Id).GetHashCode();
            }
        }

        private bool HasSameIdentifierAs(T entityToCompare)
        {
            if (!(IsTransient() && entityToCompare.IsTransient()))
                return this.Id == entityToCompare.Id;
            return false;
        }

        protected abstract void Validate();

        private List<BrokenRule> _brokenRules = new List<BrokenRule>();
        protected List<BrokenRule> BrokenRules
        {
            get { return _brokenRules; }
        }

        public ReadOnlyCollection<BrokenRule> GetBrokenRules()
        {
            this.BrokenRules.Clear();
            this.Validate();

            return _brokenRules.AsReadOnly();
        }
    }
}
